from flask import Flask, render_template, request, send_file, jsonify, Response
import pandas as pd
import numpy as np
import os
import sys
from analyze_travel_expenses import calculate_metrics, filter_by_level
import webbrowser
from threading import Timer, Thread
import glob
from process_hotel_data import process_hotel_data, save_results
from functools import lru_cache
import hashlib
import json
import time
from queue import Queue
from high_speed_route import high_speed_bp  # 导入高铁动车费用分析路由
from other_transport_route import other_transport_bp  # 导入其他交通工具费用分析路由
from flight_expense_analysis import ensure_column_types, filter_records, clean_amount  # 导入飞机费用分析路由
from flight_expense_route import flight_expense_bp  # 导入飞机费用分析路由
import high_speed_rail_analysis
import other_transport_analysis
import flight_expense_analysis
import own_vehicle_analysis
import over_day_analysis
import transport_subsidy_analysis
import accommodation_expense_analysis
import holiday_business_travel_analysis
import travel_destination_change_analysis
import meal_overstandard_analysis
import over_day_meal_analysis
import invoice_duplicate_analysis
import weekend_holiday_entertainment_analysis
import dining_receipt_analysis
import dining_sequence_analysis
import entertainment_outside_analysis
import conference_expense_analysis
import absence_analysis
import own_vehicle_2_analysis
import over_day_2_analysis
import accommodation_expense_2_analysis
import transport_subsidy_2_analysis
import over_day_meal_2_analysis
from traffic_allowance_2_analysis import analyze_six_data as analyze_six_data_2
from traffic_allowance_2_route import apply_filters_to_df
from transport_subsidy_route import transport_subsidy_bp  # 导入交通补助报销不合理模型
from traffic_allowance_analysis import analyze_six_data # 模型6
from travel_destination_change_route import travel_destination_bp  # 导入出差变更目的地模型
from weekend_holiday_entertainment_route import weekend_holiday_bp  # 导入节假日及周末公务招待分析
from dining_receipt_route import dining_receipt_bp  # 导入餐饮发票分析路由
from traffic_allowance_route import traffic_allowance_bp  # 导入交通补助分析路由
from accommodation_expense_route import accommodation_bp
from holiday_business_travel_route import holiday_travel_bp  # 导入节假日出差分析路由
from invoice_duplicate_route import invoice_duplicate_bp  # 导入发票重复分析路由
from conference_expense_route import conference_expense_bp  # 导入会议费用分析路由
from conference_people_route import conference_people_bp  # 导入会议人数超标分析路由
from conference_day_route import conference_day_bp  # 导入会议天数超标分析路由
from dining_sequence_route import dining_sequence_bp  # 导入餐饮发票连号分析路由
from entertainment_outside_jurisdiction_route import entertainment_bp  # 导入管辖范围外业务招待费分析路由
from own_vehicle_route import own_vehicle_bp  # 导入自带车报销交通补助分析路由
from over_day_route import over_day_bp  # 导入出差天数超标分析路由
from meal_overstandard_route import meal_overstandard_bp  # 导入超标准报销伙食补助分析路由
from over_day_meal_route import over_day_meal_bp  # 导入超天数报销伙食补助分析路由
from traffic_allowance_2_route import traffic_allowance_2_bp  # 导入报销在途期间外交通补助分析路由
from own_vehicle_2_route import own_vehicle_2_bp  # 导入自带车报销交通补助分析路由（培训申请）
from over_day_2_route import over_day_2_bp  # 导入超天数报销交通补助分析（培训申请）路由
from accommodation_expense_2_route import accommodation_2_bp  # 导入住宿费超标分析（培训申请）路由
from transport_subsidy_2_route import transport_subsidy_2_bp
from over_day_meal_2_route import over_day_meal_2_bp
from absence_huiyi_route import absence_huiyi_bp  # 导入外出会议未请假分析路由
from absence_peixun_route import absence_peixun_bp  # 导入外出培训未请假分析路由

def resource_path(relative_path):
    """获取资源的绝对路径"""
    try:
        # PyInstaller创建临时文件夹,将路径存储在_MEIPASS中
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")
    return os.path.join(base_path, relative_path)

app = Flask(__name__, 
            template_folder=resource_path('templates'))

# 注册蓝图
app.register_blueprint(high_speed_bp)
app.register_blueprint(other_transport_bp)  # 注册其他交通工具分析蓝图
app.register_blueprint(flight_expense_bp)  # 注册飞机费用分析蓝图
app.register_blueprint(transport_subsidy_bp)  # 注册交通补助报销不合理模型
app.register_blueprint(travel_destination_bp)  # 注册出差变更目的地模型
app.register_blueprint(weekend_holiday_bp)  # 注册节假日及周末公务招待分析蓝图
app.register_blueprint(dining_receipt_bp)  # 注册餐饮发票分析蓝图
app.register_blueprint(traffic_allowance_bp)  # 注册交通补助分析蓝图
app.register_blueprint(accommodation_bp, url_prefix='/accommodation')
app.register_blueprint(holiday_travel_bp)  # 注册节假日出差分析路由
app.register_blueprint(invoice_duplicate_bp)  # 注册发票重复分析蓝图
app.register_blueprint(conference_expense_bp)  # 注册会议费用分析蓝图
app.register_blueprint(conference_people_bp)  # 注册会议人数超标分析蓝图
app.register_blueprint(conference_day_bp)  # 注册会议天数超标分析蓝图
app.register_blueprint(dining_sequence_bp)  # 注册餐饮发票连号分析蓝图
app.register_blueprint(entertainment_bp)  # 注册管辖范围外业务招待费分析蓝图
app.register_blueprint(own_vehicle_bp, url_prefix='/own-vehicle')
app.register_blueprint(over_day_bp)  # 注册出差天数超标分析蓝图
app.register_blueprint(meal_overstandard_bp)  # 注册超标准报销伙食补助分析蓝图
app.register_blueprint(over_day_meal_bp)  # 注册超天数报销伙食补助分析蓝图
app.register_blueprint(traffic_allowance_2_bp)  # 注册报销在途期间外交通补助分析蓝图
app.register_blueprint(own_vehicle_2_bp)  # 注册自带车报销交通补助分析路由（培训申请）
app.register_blueprint(over_day_2_bp)  # 注册超天数报销交通补助分析（培训申请）蓝图
app.register_blueprint(accommodation_2_bp)  # 注册住宿费超标分析（培训申请）蓝图
app.register_blueprint(transport_subsidy_2_bp)
app.register_blueprint(over_day_meal_2_bp)
app.register_blueprint(absence_huiyi_bp)  # 注册外出会议未请假分析路由
app.register_blueprint(absence_peixun_bp)  # 注册外出培训未请假分析路由
# 配置上传文件存储路径和数据文件夹路径
if getattr(sys, 'frozen', False):
    # 如果是打包后的exe
    UPLOAD_FOLDER = os.path.join(os.path.dirname(sys.executable), 'uploads')
    DATA_FOLDER = os.path.join(os.path.dirname(sys.executable), 'data')
else:
    # 如果是开发环境
    UPLOAD_FOLDER = 'uploads'
    DATA_FOLDER = 'data'

# 确保必要的文件夹存在
for folder in [UPLOAD_FOLDER, DATA_FOLDER]:
    if not os.path.exists(folder):
        os.makedirs(folder)

# 添加全局变量来存储当前的数据状态
current_travel_data = None
current_even_odd_data = None

@app.route('/')
def index():
    return render_template('logon.html', active_page='logon')
@app.route('/close-object-model')
def close_object_model():
    # 确保只处理.exe文件
    process_name = '差旅费分析系统.exe'
    if not process_name.lower().endswith('.exe'):
        process_name += '.exe'
    
    # 使用taskkill命令
    try:
        result = subprocess.run(
            ['taskkill', '/f', '/im', process_name],
            capture_output=True,
            text=True,
            check=True
        )
        print(result.stdout)
        return True
    except subprocess.CalledProcessError as e:
        print(f"关闭进程失败: {e.stderr}")
        return False

@app.route('/travel-expense')
def travel_expense():
    return render_template('pages/travel_expense.html', active_page='travel_expense')

@app.route('/even-days-odd-cost')
def even_days_odd_cost():
    return render_template('pages/even_days_odd_cost.html', active_page='even_days_odd_cost')

@app.route('/other-transport')
def other_transport():
    return render_template('pages/other_transport.html', active_page='other_transport')

@app.route('/traffic-allowance')
def traffic_allowance():
    return render_template('pages/traffic_allowance.html', active_page='traffic_allowance')

@app.route('/travel-destination')
def travel_destination():
    return render_template('pages/travel_destination_change.html', active_page='travel_destination')

@app.route('/weekend-holiday')
def weekend_holiday():
    return render_template('pages/weekend_holiday_entertainment.html', active_page='weekend_holiday')

@app.route('/dining-receipt')
def dining_receipt():
    return render_template('pages/dining_receipt.html', active_page='dining_receipt')

@app.route('/Configure-search-parameters')
def Configure_search_parameters():
    return render_template('pages/UpperMenuPage/Configure_search_parameters.html', active_page='Configure_search_parameters')

@app.route('/Perform-one-click-search')
def Perform_one_click_search():
    return render_template('pages/UpperMenuPage/Perform_one_click_search.html', active_page='Perform_one_click_search')

@app.route('/Institutional-documents')
def Institutional_documents():
    return render_template('pages/UpperMenuPage/Institutional_documents.html', active_page='Institutional_documents')

@app.route('/Institutional-documents-details')
def Institutional_documents_details():
    return render_template('pages/UpperMenuPage/Institutional_documents_details.html', active_page='Institutional_documents_details')

@app.route('/Mold-Wall-Operation-Manual')
def Mold_Wall_Operation_Manual():
    return render_template('pages/UpperMenuPage/Mold_Wall_Operation_Manual.html', active_page='Mold_Wall_Operation_Manual')

@app.route('/accommodation-expense')
def accommodation_expense():
    return render_template('pages/accommodation_expense.html', active_page='accommodation_expense')

@app.route('/holiday-travel')
def holiday_travel():
    return render_template('pages/holiday_business_travel.html', active_page='holiday_travel')

@app.route('/invoice-duplicate')
def invoice_duplicate():
    return render_template('pages/invoice_duplicate.html', active_page='invoice_duplicate')

@app.route('/conference-expense')
def conference_expense():
    return render_template('pages/conference_expense.html', active_page='conference_expense')

@app.route('/conference-people')
def conference_people():
    return render_template('pages/conference_people.html', active_page='conference_people')

@app.route('/conference-day')
def conference_day():
    return render_template('pages/conference_day.html', active_page='conference_day')

@app.route('/dining-sequence')
def dining_sequence():
    return render_template('pages/dining_sequence.html', active_page='dining_sequence')

@app.route('/entertainment-outside')
def entertainment_outside():
    return render_template('pages/entertainment_outside.html', active_page='entertainment_outside')

@app.route('/own-vehicle')
def own_vehicle():
    return render_template('pages/own_vehicle.html', active_page='own_vehicle')

@app.route('/over-day')
def over_day():
    return render_template('pages/over_day.html', active_page='over_day')

@app.route('/meal-overstandard')
def meal_overstandard():
    return render_template('pages/meal_overstandard.html', active_page='meal_overstandard')

@app.route('/over-day-meal')
def over_day_meal():
    return render_template('pages/over_day_meal.html', active_page='over_day_meal')

@app.route('/traffic-allowance-2')
def traffic_allowance_2():
    return render_template('pages/traffic_allowance2.html', active_page='traffic_allowance_2')

@app.route('/own-vehicle-2')
def own_vehicle_2():
    return render_template('pages/own_vehicle2.html', active_page='own_vehicle_2')

@app.route('/over-day-2')
def over_day_2():
    return render_template('pages/over_day2.html', active_page='over_day_2')

@app.route('/accommodation-expense-2')
def accommodation_expense_2():
    return render_template('pages/accommodation_expense2.html', active_page='accommodation_expense_2')

@app.route('/transport-subsidy-2')
def transport_subsidy_2():
    return render_template('pages/transport_subsidy2.html', active_page='transport_subsidy_2')

@app.route('/over-day-meal-2')
def over_day_meal_2():
    return render_template('pages/over_day_meal2.html', active_page='over_day_meal_2')

@app.route('/absence-huiyi')
def absence_huiyi():
    return render_template('pages/absence_huiyi.html', active_page='absence_huiyi')

@app.route('/absence-peixun')
def absence_peixun():
    return render_template('pages/absence_peixun.html', active_page='absence_peixun')

# 添加缓存装饰器
@lru_cache(maxsize=32)
def process_travel_data(years_hash, dimension_hash = None, levels_hash=None, month_year_hash=None):
    """处理差旅费数据并缓存结果"""
    # 读取Excel文件
    file_path = os.path.join(DATA_FOLDER, '差旅费票据信息.xlsx')
    if not os.path.exists(file_path):
        return None

    try:
        df = pd.read_excel(file_path)
    except Exception as e:
        print(f"处理文件 {file_path} 时出错: {str(e)}")
        return None
    
    # 解析哈希值回到原始的列表
    years = json.loads(years_hash)
    dimension = json.loads(dimension_hash)
    month_year = json.loads(month_year_hash)
    # 计算指标
    try:
        result = calculate_metrics(df, years, dimension)
    except Exception as e:
        print(f'计算出错{e}')

    # 按档位筛选（如果选择了档位）
    try:
        if levels_hash:
            levels = json.loads(levels_hash)
            result = filter_by_level(result, levels, dimension, month_year)
    except Exception as e:
        print(f'处理档位筛选报错{e}')

    if result.empty:
        return None
        
    return result

@app.route('/analyze', methods=['POST'])
def analyze():
    try:
        global current_travel_data
        # 获取表单参数
        years = request.form.getlist('years')  # 选择的年度列表
        month_year = request.form.getlist('month_year')  # 选择的级别列表（月度/年度）
        dimension = request.form.getlist('dimension')  # 选择的维度（现在是多选）
        levels = request.form.getlist('levels')  # 选择的档位列表
        selected_fields = request.form.getlist('fields')  # 选择的字段列表
        print(years, month_year, dimension, levels, selected_fields)
        # 获取分页参数
        page = int(request.form.get('page', 1))
        per_page = 20
        
        # 参数验证
        if not years:
            return jsonify({'error': '请选择至少一个年度'}), 400
        if not month_year:
            return jsonify({'error': '请选择至少一个级别（月度或年度）'}), 400
        if not dimension:
            return jsonify({'error': '请选择查询维度'}), 400
        
        # 将years、levels、month_year和dimension列表转换为JSON字符串作为缓存键
        years_hash = json.dumps(sorted([int(y) for y in years]))
        levels_hash = json.dumps(sorted(levels)) if levels else None
        month_year_hash = json.dumps(month_year) if month_year else None
        dimension_hash = json.dumps(sorted(dimension)) if dimension else None
        # 获取处理后的数据（使用缓存）
        result_df = process_travel_data(years_hash, dimension_hash, levels_hash, month_year_hash)
        
        if result_df is None:
            return jsonify({'error': '没有找到符合条件的数据'}), 400
            
        # 根据维度过滤掉不相关的偏差率列
        if dimension == '同城市':
            result_df = result_df.drop(['同一酒店住宿费偏差率'], axis=1, errors='ignore')
        elif dimension == '同一酒店':
            result_df = result_df.drop(['同城市住宿费偏差率'], axis=1, errors='ignore')

        # 按照 "同月度同酒店住宿费偏差率" 降序排列
        if "同月度同酒店住宿费偏差率" in result_df.columns:
            result_df["排序用偏差率"] = (
                result_df["同月度同酒店住宿费偏差率"]
                .str.replace('%', '')
                .astype(float) / 100.0
            )
            result_df = result_df.sort_values(by="排序用偏差率", ascending=False).drop(columns=["排序用偏差率"])

        # 保存所有可用列信息
        all_columns = result_df.columns.tolist()
        
        # 处理选中的字段
        if selected_fields:
            # 确保所有选择的列都存在于DataFrame中
            valid_fields = [col for col in selected_fields if col in result_df.columns]
            if valid_fields:
                # 只保留选中的列
                result_df = result_df[valid_fields]
        
        # 保存当前筛选后的数据到全局变量
        current_travel_data = result_df.copy()
        
        # 计算总记录数和分页
        total_records = len(result_df)
        total_pages = (total_records + per_page - 1) // per_page
        start_idx = (page - 1) * per_page
        end_idx = start_idx + per_page
        page_data = result_df.iloc[start_idx:end_idx]
        
        # 处理 NaN 值
        page_data = page_data.replace({np.nan: None, np.inf: None, -np.inf: None})
        
        # 转换为JSON格式
        data = {
            'total_records': total_records,
            'total_pages': total_pages,
            'current_page': page,
            'data': page_data.to_dict('records'),
            'all_columns': all_columns  # 返回所有可用列的信息
        }
        
        return jsonify(data)
        
    except Exception as e:
        print(f"Error: {str(e)}")  # 添加错误日志
        return jsonify({'error': '没有找到符合条件的数据'}), 500

# 添加缓存装饰器
@lru_cache(maxsize=32)
def process_excel_data(years_hash):
    """处理Excel数据并缓存结果"""
    # 读取Excel文件
    file_path = os.path.join(DATA_FOLDER, '差旅费票据信息.xlsx')
    if not os.path.exists(file_path):
        return None
    
    try:
        df = pd.read_excel(file_path)
    except Exception as e:
        print(f"处理文件 {file_path} 时出错: {str(e)}")
        return None
    
    # 解析years_hash回到原始的years列表
    years = json.loads(years_hash)
    
    # 按年度筛选
    df = df[df['年度'].isin(years)]

    # 只保留发票号码不为空的数据
    df = df[df['发票号码'].notna() & (df['发票号码'].astype(str).str.strip() != '')]

    # 只保留住宿天数不为0，不为0.00的数据
    df = df[~((df['住宿天数'] == 0) | (df['住宿天数'] == 0.00))]

    if df.empty:
        return None
        
    # 处理数据：检查住宿天数是否为偶数且发票金额是否为奇数
    def is_even(price, num):
        try:
            # return float(num).is_integer() and int(float(num)) % 2 == 0
            res = float(price)/int(num)
            # 判断 res 是否不为0并且是小数
            return res != 0 and not res.is_integer()
        except:
            return False
            
    # def is_odd(price, num):
    #     try:
    #         return float(num).is_integer() and int(float(num)) % 2 == 1
    #     except:
    #         return False
    
    # 添加判断结果列
    df['发票金额/发票含税金额都不为整数'] = df.apply(
        lambda row: '是' if is_even(row['发票金额'], row['住宿天数']) and is_even(row['发票含税金额'], row['住宿天数']) else '否',
        axis=1
    )
    
    # 只保留标记为"是"的记录
    result_df = df[df['发票金额/发票含税金额都不为整数'] == '是'].copy()
    
    if result_df.empty:
        return None
    
    return result_df

@app.route('/analyze-even-odd', methods=['POST'])
def analyze_even_odd():
    try:
        global current_even_odd_data
        # 获取表单参数
        years = request.form.getlist('years')  # 选择的年度列表
        selected_fields = request.form.getlist('fields')  # 选择的字段列表
        page = int(request.form.get('page', 1))
        per_page = 20
        
        # 参数验证
        if not years:
            return jsonify({'error': '请选择至少一个年度'}), 400
            
        # 将years列表转换为JSON字符串作为缓存键
        years_hash = json.dumps(sorted([int(y) for y in years]))

        # 获取处理后的数据（使用缓存）
        result_df = process_excel_data(years_hash)
        
        if result_df is None:
            return jsonify({'error': '没有找到符合条件的数据'}), 400

        # 保存所有可用列信息
        all_columns = result_df.columns.tolist()
        
        # 处理选中的字段
        if selected_fields:
            # 确保所有选择的列都存在于DataFrame中
            valid_fields = [col for col in selected_fields if col in result_df.columns]
            if valid_fields:
                # 只保留选中的列
                result_df = result_df[valid_fields]
        
        # 保存当前筛选后的数据到全局变量
        current_even_odd_data = result_df.copy()
        
        # 计算总记录数和分页
        total_records = len(result_df)
        total_pages = (total_records + per_page - 1) // per_page
        start_idx = (page - 1) * per_page
        end_idx = start_idx + per_page
        page_data = result_df.iloc[start_idx:end_idx]
        
        # 处理 NaN 值
        page_data = page_data.replace({np.nan: None, np.inf: None, -np.inf: None})
        
        # 转换为JSON格式
        data = {
            'total_records': total_records,
            'total_pages': total_pages,
            'current_page': page,
            'data': page_data.to_dict('records'),
            'all_columns': all_columns
        }
        
        return jsonify(data)
        
    except Exception as e:
        print(f"Error in analyze_even_odd: {str(e)}")
        return jsonify({'error': '没有找到符合条件的数据'}), 500

@app.route('/download-travel-excel')
def download_travel_excel():
    try:
        global current_travel_data
        if current_travel_data is None:
            return jsonify({'error': '请先查询数据再下载'}), 400
            
        # 创建临时文件用于下载
        output_path = os.path.join(UPLOAD_FOLDER, 'travel_analysis_result.xlsx')
        current_travel_data.to_excel(output_path, index=False)
        
        return send_file(
            output_path,
            as_attachment=True,
            download_name='差旅费分析结果.xlsx',
            mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
        )
    except Exception as e:
        print(f"Download error: {str(e)}")
        return jsonify({'error': f'下载文件时发生错误: {str(e)}'}), 500

@app.route('/download-even-odd-excel')
def download_even_odd_excel():
    try:
        global current_even_odd_data
        if current_even_odd_data is None:
            return jsonify({'error': '请先查询数据再下载'}), 400
            
        # 创建临时文件用于下载
        output_path = os.path.join(UPLOAD_FOLDER, 'even_odd_analysis_result.xlsx')
        current_even_odd_data.to_excel(output_path, index=False)
        
        return send_file(
            output_path,
            as_attachment=True,
            download_name='偶数天数奇数金额分析结果.xlsx',
            mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
        )
    except Exception as e:
        print(f"Download error: {str(e)}")
        return jsonify({'error': f'下载文件时发生错误: {str(e)}'}), 500

@app.route('/progress', methods=['GET', 'POST'])
def progress():
    """处理实时进度更新请求"""
    try:
        if request.method == 'GET':
            # EventSource请求
            data_str = request.args.get('data')
            if not data_str:
                return jsonify({'error': '缺少数据参数'}), 400
            
            data = json.loads(data_str)
        else:
            # POST请求
            data = request.get_json()
        
        selected_models = data.get('selectedModels', [])
        model_configs = data.get('modelConfigs', {})
        
        print(f"Progress: 接收到的模型: {selected_models}")
        print(f"Progress: 接收到的配置: {model_configs}")
        
        if not selected_models:
            return jsonify({'error': '请至少选择一个模型'}), 400
        
        def generate():
            """生成实时进度更新"""
            all_results = {}
            progress_queue = Queue()
            
            def process_model_thread(model_id, config):
                """在后台线程中处理模型"""
                try:
                    # 处理模型
                    result = False
                    if model_id == '1' and '1' in model_configs:
                        result = process_model_1(model_configs['1'])
                    elif model_id == '2' and '2' in model_configs:
                        result = process_model_2(model_configs['2'])
                    elif model_id == '3' and '3' in model_configs:
                        result = process_model_3(model_configs['3'])
                    elif model_id == '4' and '4' in model_configs:
                        result = process_model_4(model_configs['4'])
                    elif model_id == '5':
                        result = process_model_5()
                    elif model_id == '6' and '6' in model_configs:
                        result = process_model_6(model_configs['6'])
                    elif model_id == '7' and '7' in model_configs:
                        result = process_model_7(model_configs['7'])
                    elif model_id == '8' and '8' in model_configs:
                        result = process_model_8(model_configs['8'])
                    elif model_id == '9':
                        result = process_model_9()
                    elif model_id == '10':
                        result = process_model_10()
                    elif model_id == '11' and '11' in model_configs:
                        result = process_model_11(model_configs['11'])
                    elif model_id == '12' and '12' in model_configs:
                        result = process_model_12(model_configs['12'])
                    elif model_id == '13':
                        result = process_model_13()
                    elif model_id == '14' and '14' in model_configs:
                        result = process_model_14(model_configs['14'])
                    elif model_id == '15':
                        result = process_model_15()
                    elif model_id == '16' and '16' in model_configs:
                        result = process_model_16(model_configs['16'])
                    elif model_id == '17' and '17' in model_configs:
                        result = process_model_17(model_configs['17'])
                    elif model_id == '18' and '18' in model_configs:
                        result = process_model_18(model_configs['18'])
                    elif model_id == '19' and '19' in model_configs:
                        result = process_model_19(model_configs['19'])
                    elif model_id in ['20', '21', '22']:
                        result = process_model_20()
                    elif model_id == '23':
                        result = process_model_23()
                    elif model_id == '24' and '24' in model_configs:
                        result = process_model_24(model_configs['24'])
                    elif model_id == '25' and '25' in model_configs:
                        result = process_model_25(model_configs['25'])
                    elif model_id == '26' and '26' in model_configs:
                        result = process_model_26(model_configs['26'])
                    elif model_id == '27':
                        result = process_model_27()
                    elif model_id == '28':
                        result = process_model_28()
                    elif model_id == '29':
                        result = process_model_29()
                    elif model_id == '30' and '30' in model_configs:
                        result = process_model_30(model_configs['30'])
                    
                    all_results[f'model_{model_id}'] = result
                    
                    # 发送处理完成的消息
                    if result:
                        progress_data = {
                            'type': 'progress',
                            'modelId': model_id,
                            'status': 'success',
                            'message': '处理成功'
                        }
                    else:
                        progress_data = {
                            'type': 'progress',
                            'modelId': model_id,
                            'status': 'error',
                            'message': '处理失败'
                        }
                    
                    progress_queue.put(progress_data)
                    
                except Exception as e:
                    print(f"Progress: 模型 {model_id} 处理异常: {str(e)}")
                    all_results[f'model_{model_id}'] = False
                    progress_data = {
                        'type': 'progress',
                        'modelId': model_id,
                        'status': 'error',
                        'message': f'处理失败: {str(e)}'
                    }
                    progress_queue.put(progress_data)
            
            # 启动所有模型的处理线程
            threads = []
            for model_id in selected_models:
                # 发送开始处理的消息
                progress_data = {
                    'type': 'progress',
                    'modelId': model_id,
                    'status': 'processing',
                    'message': '正在处理中...'
                }
                message = f"data: {json.dumps(progress_data, ensure_ascii=False)}\n\n"
                yield message
                
                # 启动处理线程
                thread = Thread(target=process_model_thread, args=(model_id, model_configs))
                thread.daemon = True
                thread.start()
                threads.append(thread)
            
            # 等待所有线程完成并发送进度更新
            completed_count = 0
            while completed_count < len(selected_models):
                try:
                    # 非阻塞方式检查队列
                    progress_data = progress_queue.get(timeout=0.1)
                    message = f"data: {json.dumps(progress_data, ensure_ascii=False)}\n\n"
                    yield message
                    completed_count += 1
                except:
                    # 超时，继续等待
                    time.sleep(0.1)
                    continue
            
            # 发送完成消息
            success_count = sum(1 for result in all_results.values() if result)
            total_count = len(all_results)
            
            completion_data = {
                'type': 'completion',
                'success': True,
                'message': f'所有模型分析完成，{success_count}/{total_count} 个模型处理成功',
                'results': all_results
            }
            message = f"data: {json.dumps(completion_data, ensure_ascii=False)}\n\n"
            yield message
        
        return Response(generate(), mimetype='text/event-stream', headers={
            'Cache-Control': 'no-cache',
            'Connection': 'keep-alive',
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Headers': 'Cache-Control'
        })
        
    except Exception as e:
        print("progress 错误: {}".format(str(e)))
        return jsonify({'error': '处理进度更新时发生错误: {}'.format(str(e))}), 500

@app.route('/download_all', methods=['POST'])
def download_all():
    """处理一键查询请求"""
    try:
        data = request.get_json()
        selected_models = data.get('selectedModels', [])
        model_configs = data.get('modelConfigs', {})
        
        if not selected_models:
            return jsonify({'error': '请至少选择一个模型'}), 400
        
        # 处理每个选中的模型
        all_results = {}
        
        for model_id in selected_models:
            print("正在处理模型: {}".format(model_id))
            
            if model_id == '1' and '1' in model_configs:
                # 处理模型1：标准限额内虚开住宿费模型
                result = process_model_1(model_configs['1'])
                all_results['model_1'] = result
                print("模型1处理完成")
                
            elif model_id == '2' and '2' in model_configs:
                # 处理模型2：住宿天数为偶数但住宿费为奇数模型
                result = process_model_2(model_configs['2'])
                all_results['model_2'] = result
                print("模型2处理完成")
                
            elif model_id == '3' and '3' in model_configs:
                # 处理模型3：超标准全额报销高铁动车费模型
                result = process_model_3(model_configs['3'])
                all_results['model_3'] = result
                print("模型3处理完成")
                
            elif model_id == '4' and '4' in model_configs:
                # 处理模型4：超标准乘坐交通工具模型
                result = process_model_4(model_configs['4'])
                all_results['model_4'] = result
                print("模型4处理完成")
                
            elif model_id == '5':
                # 处理模型5：超标准报销住宿费模型
                result = process_model_5()
                all_results['model_5'] = result
                print("模型5处理完成")
                
            elif model_id == '6' and '6' in model_configs:
                # 处理模型6：报销在途期间外交通补助模型
                result = process_model_6(model_configs['6'])
                all_results['model_6'] = result
                print("模型6处理完成")
                
            elif model_id == '7' and '7' in model_configs:
                # 处理模型7：自带车出差却报销交通补助模型
                result = process_model_7(model_configs['7'])
                all_results['model_7'] = result
                print("模型7处理完成")
                
            elif model_id == '8' and '8' in model_configs:
                # 处理模型8：超天数报销交通补助模型
                result = process_model_8(model_configs['8'])
                all_results['model_8'] = result
                print("模型8处理完成")
                
            elif model_id == '9':
                # 处理模型9：超标准报销伙食补助模型
                result = process_model_9()
                all_results['model_9'] = result
                print("模型9处理完成")
                
            elif model_id == '10':
                # 处理模型10：超天数伙食交通补助模型
                result = process_model_10()
                all_results['model_10'] = result
                print("模型10处理完成")
                
            elif model_id == '11' and '11' in model_configs:
                # 处理模型11：节假日出差模型
                result = process_model_11(model_configs['11'])
                all_results['model_11'] = result
                print("模型11处理完成")
                
            elif model_id == '12' and '12' in model_configs:
                # 处理模型12：出差变更目的地不合理模型
                result = process_model_12(model_configs['12'])
                all_results['model_12'] = result
                print("模型12处理完成")
                
            elif model_id == '13':
                # 处理模型13：超标准报销伙食补助模型
                result = process_model_13()
                all_results['model_13'] = result
                print("模型13处理完成")
                
            elif model_id == '14' and '14' in model_configs:
                # 处理模型14：超天数伙食交通补助模型
                result = process_model_14(model_configs['14'])
                all_results['model_14'] = result
                print("模型14处理完成")
                
            elif model_id == '15':
                # 处理模型15：一张发票多次报销模型
                result = process_model_15()
                all_results['model_15'] = result
                print("模型15处理完成")
                
            elif model_id == '16' and '16' in model_configs:
                # 处理模型16：节假日、周末发生招待模型
                result = process_model_16(model_configs['16'])
                all_results['model_16'] = result
                print("模型16处理完成")
                
            elif model_id == '17' and '17' in model_configs:
                # 处理模型17：虚开业务招待发票模型
                result = process_model_17(model_configs['17'])
                all_results['model_17'] = result
                print("模型17处理完成")
                
            elif model_id == '18' and '18' in model_configs:
                # 处理模型18：单一销方单位连号模型
                result = process_model_18(model_configs['18'])
                all_results['model_18'] = result
                print("模型18处理完成")
                
            elif model_id == '19' and '19' in model_configs:
                # 处理模型19：公司管辖范围外发生业务招待费模型
                result = process_model_19(model_configs['19'])
                all_results['model_19'] = result
                print("模型19处理完成")
                
            elif model_id in ['20', '21', '22']:
                # 处理模型20：主办会议人数超标模型
                result = process_model_20()
                all_results['model_20'] = result
                print("模型20、21、22处理完成")
                
            elif model_id == '23':
                # 处理模型23：外出会议未请假模型
                result = process_model_23()
                all_results['model_23'] = result
                print("模型23处理完成")
                
            elif model_id == '24' and '24' in model_configs:
                # 处理模型24：报销在途期间外交通补助模型
                print(model_configs['24'])
                result = process_model_24(model_configs['24'])
                all_results['model_24'] = result
                print("模型24处理完成")
                
            elif model_id == '25' and '25' in model_configs:
                # 处理模型25：自带车出差却报销交通补助模型
                result = process_model_25(model_configs['25'])
                all_results['model_25'] = result
                print("模型25处理完成")
                
            elif model_id == '26' and '26' in model_configs:
                # 处理模型26：超天数报销交通补助模型
                result = process_model_26(model_configs['26'])
                all_results['model_26'] = result
                print("模型26处理完成")
                
            elif model_id == '27':
                # 处理模型27：超标准报销住宿费模型
                result = process_model_27()
                all_results['model_27'] = result
                print("模型27处理完成")
                
            elif model_id == '28':
                # 处理模型28：出差日期重叠重复报销模型
                result = process_model_28()
                all_results['model_28'] = result
                print("模型28处理完成")
                
            elif model_id == '29':
                # 处理模型29：外出培训未请假模型
                result = process_model_29()
                all_results['model_29'] = result
                print("模型29处理完成")
                
            elif model_id == '30' and '30' in model_configs:
                # 处理模型30：超天数报销伙食补助模型
                result = process_model_30(model_configs['30'])
                all_results['model_30'] = result
                print("模型30处理完成")
        
        # 检查处理结果
        success_count = sum(1 for result in all_results.values() if result)
        total_count = len(all_results)
        
        if total_count > 0:
            return jsonify({
                'success': True,
                'message': '所有模型分析完成，{}/{} 个模型处理成功'.format(success_count, total_count),
                'receivedModels': selected_models,
                'results': all_results
            })
        else:
            return jsonify({
                'success': False,
                'message': '没有选择任何模型或所有模型处理失败',
                'receivedModels': selected_models,
                'results': all_results
            })
        
    except Exception as e:
        print("download_all 错误: {}".format(str(e)))
        return jsonify({'error': '处理参数配置时发生错误: {}'.format(str(e))}), 500

def process_model_1(config):
    """处理模型1：标准限额内虚开住宿费模型"""
    name = "1：标准限额内虚开住宿费模型"
    try:
        # 获取配置参数
        years = config.get('years', [])
        month_year = config.get('month_year', [])  # 新增：级别参数
        dimension = config.get('dimension', '')
        levels = config.get('levels', [])

        # 参数验证
        if not years:
            return False
        else:
            years = [int(year) for year in years]
        if not month_year:
            return False
        if not dimension:
            return False
        if not levels:
            return False

        # 使用相对路径读取数据文件

        data_file_path = os.path.join(DATA_FOLDER, "差旅费票据信息.xlsx")
        print("正在读取数据文件: {}".format(data_file_path))
        df = pd.read_excel(data_file_path)

        # 计算指标
        result = calculate_metrics(df, years, dimension)

        # 按档位筛选
        filtered_result = filter_by_level(result, levels, dimension, month_year)

        # 确保输出目录存在
        output_dir = os.path.join(DATA_FOLDER, "alldata")

        # 保存结果
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        filtered_result.to_excel(output_file, index=False)
        print("模型1文件已保存: {}".format(output_file))
        return True

    except Exception as e:
        print("模型1处理错误: {}".format(str(e)))
        return False

def process_model_2(config):
    """处理模型2：住宿天数为偶数但住宿费为奇数模型"""
    name = "2：住宿天数为偶数但住宿费为奇数模型"
    try:
        # 获取配置参数
        years = config.get('years', [])

        # 参数验证
        if not years:
            return False

        # 将years列表转换为JSON字符串作为缓存键
        years_hash = json.dumps(sorted([int(y) for y in years]))

        # 获取处理后的数据（使用缓存）
        result_df = process_excel_data(years_hash)

        if result_df is None:
            return {'error': '没有找到符合条件的数据'}

        # 处理 NaN 值
        result_df = result_df.replace({np.nan: None, np.inf: None, -np.inf: None})

        # 确保输出目录存在
        output_dir = os.path.join(DATA_FOLDER, "alldata")

        # 保存结果
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        result_df.to_excel(output_file, index=False)
        return True
    except Exception as e:
        print("模型2处理错误: {}".format(str(e)))
        return False

def process_model_3(config):
    """处理模型3：超标准全额报销高铁动车费模型"""
    name = "3：超标准全额报销高铁动车费模型"
    try:
        # 获取配置参数
        threshold = float(config.get('threshold', ''))
        try:
            data_file_path = os.path.join(DATA_FOLDER, "alldata/高铁动车费用超标分析结果.xlsx")
            data = pd.read_excel(data_file_path)
        except:
            data = high_speed_rail_analysis.main(True)
            output_dir = os.path.join(DATA_FOLDER, "alldata/高铁动车费用超标分析结果.xlsx")
            data.to_excel(output_dir, index=False, engine='openpyxl')
        data['超出率_数值'] = data['超出率'].apply(
            lambda x: float(x.replace('%', '')) if isinstance(x, str) and x != '-' else None)
        data = data[data["超出率_数值"] > threshold]
        data = data.drop('超出率_数值', axis=1)

        # 保存到Excel文件
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        data.to_excel(output_file, index=False)
        print("模型3文件已保存: /data/alldata/{}.xlsx".format(name))
        return True

    except Exception as e:
        print("模型3处理错误: {}".format(str(e)))
        return False

def process_model_4(config):
    """处理模型4：超标准乘坐交通工具模型"""
    name = "4：超标准乘坐交通工具模型"
    try:
        # 获取配置参数
        threshold = float(config.get('threshold', ''))
        try:
            data_file_path = os.path.join(DATA_FOLDER, "alldata/其他交通工具费用超标分析结果.xlsx")
            data = pd.read_excel(data_file_path)
        except:
            data = other_transport_analysis.main(True)
            output_dir = os.path.join(DATA_FOLDER, "alldata/其他交通工具费用超标分析结果.xlsx")
            data.to_excel(output_dir, index=False, engine='openpyxl')
        data['超出率_数值'] = data['超出率'].apply(
            lambda x: float(x.replace('%', '')) if isinstance(x, str) and x != '-' else None)

        data = data[data["超出率_数值"] > threshold]
        data = data.drop('超出率_数值', axis=1)
        # 保存到Excel文件
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        data.to_excel(output_file, index=False)
        print("模型4文件已保存: /data/alldata/{}.xlsx".format(name))
        return True
        
    except Exception as e:
        print("模型4处理错误: {}".format(str(e)))
        return False

def process_model_5():
    """处理模型5：乘坐飞机经济舱审批是否合规模型"""
    name = "5：乘坐飞机经济舱审批是否合规模型"
    try:
        data = flight_expense_analysis.main(True)
        # 保存结果
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        data.to_excel(output_file, index=False)
        print("模型5文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型5处理错误: {}".format(str(e)))
        return False

def process_model_6(config):
    """处理模型6：报销在途期间外交通补助模型"""
    name = "6：报销在途期间外交通补助模型"
    try:
        # 获取配置参数
        filter_text = config.get('filter', '')
        filter2_text = config.get('filter2', '')

        if not filter_text:
            return False

        # 确保输出目录存在
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        application_path = os.path.join(DATA_FOLDER, '商旅申请单据.xlsx')
        allowance_path = os.path.join(DATA_FOLDER, '差旅费出差补助.xlsx')
        results = analyze_six_data(application_path, allowance_path, filter_text, filter2_text, True)
        # 保存到Excel文件
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        results.to_excel(output_file, index=False)
        print("模型6文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型6处理错误: {}".format(str(e)))
        return False

def process_model_7(config):
    """处理模型7：自带车出差却报销交通补助模型"""
    name = "7：自带车出差却报销交通补助模型"
    try:
        # 获取配置参数
        # level_one = config.get('levelOne', True)
        # level_two = config.get('levelTwo', True)
        # select_ = []
        # if level_one:
        #     select_.append("一级")
        # if level_two:
        #     select_.append("二级")

        # if not select_:
        #     return False

        # 确保输出目录存在
        df = own_vehicle_analysis.main(True)
        # if len(select_):
        #     df = df[df["优先级"].isin(select_)]
        
        # 保存到Excel文件
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        df.to_excel(output_file, index=False)
        print("模型7文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型7处理错误: {}".format(str(e)))
        return False

def process_model_8(config):
    """处理模型8：超天数报销交通补助模型"""
    name = "8：超天数报销交通补助模型"
    try:
        # 获取配置参数
        level_one = config.get('levelOne', True)
        level_two = config.get('levelTwo', True)
        select_ = []
        if level_one:
            select_.append("一级")
        if level_two:
            select_.append("二级")

        if not select_:
            return False

        # 确保输出目录存在
        df = over_day_analysis.main(True)
        if len(select_):
            df = df[df["优先级"].isin(select_)]

        # 保存到Excel文件
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        df.to_excel(output_file, index=False)
        print("模型8文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型8处理错误: {}".format(str(e)))
        return False

def process_model_9():
    """处理模型9：超标准报销住宿费模型"""
    name = "9：超标准报销住宿费模型"
    try:
        # 确保输出目录存在
        data = accommodation_expense_analysis.main(True)

        output_dir = os.path.join(DATA_FOLDER, "alldata")
        # 保存到Excel文件
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        data.to_excel(output_file, index=False)
        print("模型9文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型9处理错误: {}".format(str(e)))
        return False

def process_model_10():
    """处理模型10：出差日期重叠重复报销模型"""
    name = "10：出差日期重叠重复报销模型"
    try:
        data = transport_subsidy_analysis.main(True)
        # 确保输出目录存在
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        data.to_excel(output_file, index=False)
        print("模型10文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型10处理错误: {}".format(str(e)))
        return False

def process_model_11(config):
    """处理模型11：节假日出差模型"""
    name = "11：节假日出差模型"
    try:
        # 获取配置参数
        level_one = config.get('levelOne', True)
        level_two = config.get('levelTwo', True)
        level_three = config.get('levelThree', True)
        select_ = []
        if level_one:
            select_.append("一级")
        if level_two:
            select_.append("二级")
        if level_three:
            select_.append("三级")

        if not select_:
            return False

        # 创建模拟数据
        data = holiday_business_travel_analysis.main(True)
        if len(select_):
            data = data[data["城市优先级"].isin(select_)]
        # 确保输出目录存在
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        data.to_excel(output_file, index=False)
        print("模型11文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型11处理错误: {}".format(str(e)))
        return False

def process_model_12(config):
    """处理模型12：出差变更目的地不合理模型"""
    name = "12：出差变更目的地不合理模型"
    try:
        # 获取配置参数
        level_one = config.get('levelOne', True)
        level_two = config.get('levelTwo', True)
        select_ = []
        if level_one:
            select_.append("一级")
        if level_two:
            select_.append("二级")

        if not select_:
            return False

        data = travel_destination_change_analysis.main(True)
        if len(select_):
            data = data[data["目的地等级"].isin(select_)]
        # 确保输出目录存在

        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        data.to_excel(output_file, index=False)
        print("模型12文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型12处理错误: {}".format(str(e)))
        return False

def process_model_13():
    """处理模型13：超标准报销伙食补助模型"""
    name = "13：超标准报销伙食补助模型"
    try:
        data = meal_overstandard_analysis.main(True)
        # 确保输出目录存在
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        # 保存到Excel文件
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        data.to_excel(output_file, index=False)
        print("模型13文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型13处理错误: {}".format(str(e)))
        return False

def process_model_14(config):
    """处理模型14：超天数伙食交通补助模型"""
    name = "14：超天数伙食交通补助模型"
    try:
        # 获取配置参数
        level_one = config.get('levelOne', True)
        level_two = config.get('levelTwo', True)
        select_ = []
        if level_one:
            select_.append("一级")
        if level_two:
            select_.append("二级")

        if not select_:
            return False

        data = over_day_meal_analysis.main(True)
        if len(select_):
            data = data[data["优先级"].isin(select_)]

        # 确保输出目录存在
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        data.to_excel(output_file, index=False)
        print("模型14文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型14处理错误: {}".format(str(e)))
        return False

def process_model_15():
    """处理模型15：一张发票多次报销模型"""
    name = "15：一张发票多次报销模型"
    try:
        data = invoice_duplicate_analysis.main(True)

        # 确保输出目录存在
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        data.to_excel(output_file, index=False)
        print("模型15文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型15处理错误: {}".format(str(e)))
        return False

def process_model_16(config):
    """处理模型16：节假日、周末发生招待模型"""
    name = "16：节假日、周末发生招待模型"
    try:
        # 获取配置参数
        level_one = config.get('levelOne', True)  # 按开票日期筛选
        level_two = config.get('levelTwo', True)  # 按实际发生日期筛选

        if level_one + level_two == 0:
            return False

        data = weekend_holiday_entertainment_analysis.main(True)

        if level_one or level_two:
            if level_one and level_two:
                # 两个条件都选中时，满足任一条件即可
                data = data[
                    (data['开票日期是否发生招待'] == '是') |
                    (data['实际发生日期是否发生招待'] == '是')
                ]
            elif level_one:
                data = data[data['开票日期是否发生招待'] == '是']
            elif level_two:
                data = data[data['实际发生日期是否发生招待'] == '是']

        # 确保输出目录存在
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        data.to_excel(output_file, index=False)
        print("模型16文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型16处理错误: {}".format(str(e)))
        return False

def process_model_17(config):
    """处理模型17：虚开业务招待发票模型"""
    name = "17：虚开业务招待发票模型"
    try:
        # 获取配置参数
        risk_level_1 = config.get('sellerLevelOne', True)  # 一级销方单位
        risk_level_2 = config.get('sellerLevelTwo', True)  # 二级销方单位
        amount_level_1 = config.get('invoiceLevelOne', True)  # 发票一级
        amount_level_2 = config.get('invoiceLevelTwo', True)  # 发票二级


        if risk_level_1 + risk_level_2 == 0:return False
        if amount_level_1 + amount_level_2 == 0:return False

        data = dining_receipt_analysis.main(True)
        # 应用筛选条件

        risk_ = []
        if risk_level_1:
            risk_.append("一级")
        if risk_level_2:
            risk_.append("二级")

        if len(risk_):
            data = data[data["风险等级"].isin(risk_)]

        amount_ = []
        if amount_level_1:
            amount_.append("一级")
        if amount_level_2:
            amount_.append("二级")

        if len(amount_):
            data = data[data["发票金额等级"].isin(amount_)]

        # 确保输出目录存在
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        data.to_excel(output_file, index=False)
        print("模型17文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型17处理错误: {}".format(str(e)))
        return False

def process_model_18(config):
    """处理模型18：单一销方单位连号模型"""
    name = "18：单一销方单位连号模型"
    try:
        # 获取配置参数
        risk_level_1 = config.get('levelOne', True)  # 一级风险
        risk_level_2 = config.get('levelTwo', True)  # 二级风险
        amount_level_1 = config.get('invoiceLevelOne', True)  # 发票一级
        amount_level_2 = config.get('invoiceLevelTwo', True)  # 发票二级

        if risk_level_1 + risk_level_2 == 0:return False
        if amount_level_1 + amount_level_2 == 0:return False

        data = dining_sequence_analysis.main(True)

        risk_ = []
        if risk_level_1:
            risk_.append("一级")
        if risk_level_2:
            risk_.append("二级")

        if len(risk_):
            data = data[data["风险等级"].isin(risk_)]

        amount_ = []
        if amount_level_1:
            amount_.append("一级")
        if amount_level_2:
            amount_.append("二级")

        if len(amount_):
            data = data[data["发票金额等级"].isin(amount_)]

        # 确保输出目录存在
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        data.to_excel(output_file, index=False)
        print("模型18文件已保存: {}".format(output_file))
        return True
    except Exception as e:
        print("模型18处理错误: {}".format(str(e)))
        return False

def process_model_19(config):
    """处理模型19：公司管辖范围外发生业务招待费模型"""
    name = "19：公司管辖范围外发生业务招待费模型"
    try:
        # 获取配置参数
        risk_level_1 = config.get('riskLevelOne', True)  # 一级风险
        risk_level_2 = config.get('riskLevelTwo', True)  # 二级风险
        address_match_one = config.get('addressMatchOne', True)  # 不匹配
        address_match_two = config.get('addressMatchTwo', True)  # 税号地址未知
        address_match_three = config.get('addressMatchThree', True)  # 组织所在地未知

        risk_ = []
        if risk_level_1:
            risk_.append("一级")
        if risk_level_2:
            risk_.append("二级")

        if not risk_:
            return False

        match_status = []
        if address_match_one:
            match_status.append("不匹配")
        if address_match_two:
            match_status.append("税号地址未知")
        if address_match_three:
            match_status.append("组织所在地未知")

        if not match_status:
            return False

        data = entertainment_outside_analysis.main(True)
        # 应用筛选条件

        if len(risk_):
            data = data[data["风险等级"].isin(risk_)]

        if len(match_status):
            data = data[data["地址匹配状态"].isin(match_status)]
        
        # 确保输出目录存在
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        data.to_excel(output_file, index=False)
        print("模型19文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型19处理错误: {}".format(str(e)))
        return False

def process_model_20():
    """处理模型20：主办会议人数超标模型"""
    name20 = "20：主办会议人数超标模型"
    name21 = "21：主办会议天数超标模型"
    name22 = "22：主办会议金额超标模型"
    try:

        data20, data21, data22 = conference_expense_analysis.analyze_conferences(True)
        # 确保输出目录存在
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name20))
        data20.to_excel(output_file, index=False)
        print("模型20文件已保存: {}".format(output_file))
        output_file = os.path.join(output_dir, "{}.xlsx".format(name21))
        data21.to_excel(output_file, index=False)
        print("模型21文件已保存: {}".format(output_file))
        output_file = os.path.join(output_dir, "{}.xlsx".format(name22))
        data22.to_excel(output_file, index=False)
        print("模型22文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型20、21、22处理错误: {}".format(str(e)))
        return False

def process_model_23():
    """处理模型23：外出会议未请假模型"""
    name = "23：外出会议未请假模型"
    try:
        data = absence_analysis.main(True)[0]

        # 确保输出目录存在
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        data.to_excel(output_file, index=False)
        print("模型23文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型23处理错误: {}".format(str(e)))
        return False

def process_model_24(config):
    """处理模型24：报销在途期间外交通补助模型"""
    name = "24：报销在途期间外交通补助模型"
    try:
        # 获取配置参数
        filter_text = config.get('filter', '')  # 筛选条件
        filter2_text = config.get('filter2', '')  # 过滤条件

        if not filter_text:return False

        application_path = os.path.join(DATA_FOLDER, '商旅申请单据.xlsx')
        allowance_path = os.path.join(DATA_FOLDER, '差旅费出差补助.xlsx')
        results = analyze_six_data_2(application_path, allowance_path, filter_text, filter2_text, True)
        # 确保输出目录存在
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        results.to_excel(output_file, index=False)
        print("模型24文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型24处理错误: {}".format(str(e)))
        return False

def process_model_25(config):
    """处理模型25：自带车出差却报销交通补助模型"""
    name = "25：自带车出差却报销交通补助模型"
    try:
        # 获取配置参数
        level_one = config.get('levelOne', True)  # 一级优先级
        level_two = config.get('levelTwo', True)  # 二级优先级

        select_ = []
        if level_one:
            select_.append("一级")
        if level_two:
            select_.append("二级")

        if not select_:
            return False

        data = own_vehicle_2_analysis.main(True)
        if len(select_):
            data = data[data["优先级"].isin(select_)]

        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        data.to_excel(output_file, index=False)
        print("模型25文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型25处理错误: {}".format(str(e)))
        return False

def process_model_26(config):
    """处理模型26：超天数报销交通补助模型"""
    name = "26：超天数报销交通补助模型"
    try:
        # 获取配置参数
        level_one = config.get('levelOne', True)  # 一级优先级
        level_two = config.get('levelTwo', True)  # 二级优先级

        select_ = []
        if level_one:
            select_.append("一级")
        if level_two:
            select_.append("二级")

        if not select_:
            return False

        data = over_day_2_analysis.main(True)
        if len(select_):
            data = data[data["优先级"].isin(select_)]
        # 确保输出目录存在
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        data.to_excel(output_file, index=False)
        print("模型26文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型26处理错误: {}".format(str(e)))
        return False

def process_model_27():
    """处理模型27：超标准报销住宿费模型"""
    name = "27：超标准报销住宿费模型"
    try:

        data = accommodation_expense_2_analysis.main(True)
        # 确保输出目录存在
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        data.to_excel(output_file, index=False)
        print("模型27文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型27处理错误: {}".format(str(e)))
        return False

def process_model_28():
    """处理模型28：出差日期重叠重复报销模型"""
    name = "28：出差日期重叠重复报销模型"
    try:

        data = transport_subsidy_2_analysis.main(True)
        # 确保输出目录存在
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        data.to_excel(output_file, index=False)
        print("模型28文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型28处理错误: {}".format(str(e)))
        return False

def process_model_29():
    """处理模型29：外出培训未请假模型"""
    name = "29：外出培训未请假模型"
    try:

        data = absence_analysis.main(True)[1]
        # 确保输出目录存在
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        data.to_excel(output_file, index=False)
        print("模型29文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型29处理错误: {}".format(str(e)))
        return False

def process_model_30(config):
    """处理模型30：超天数报销伙食补助模型"""
    name = "30：超天数报销伙食补助模型"
    try:
        # 获取配置参数
        level_one = config.get('levelOne', True)  # 一级优先级
        level_two = config.get('levelTwo', True)  # 二级优先级

        select_ = []
        if level_one:
            select_.append("一级")
        if level_two:
            select_.append("二级")

        if not select_:
            return False

        data = over_day_meal_2_analysis.main(True)
        if len(select_):
            data = data[data["优先级"].isin(select_)]
        
        # 确保输出目录存在
        output_dir = os.path.join(DATA_FOLDER, "alldata")
        output_file = os.path.join(output_dir, "{}.xlsx".format(name))
        data.to_excel(output_file, index=False)
        print("模型30文件已保存: {}".format(output_file))
        return True
        
    except Exception as e:
        print("模型30处理错误: {}".format(str(e)))
        return False

def open_browser():
    webbrowser.open('http://127.0.0.1:5000/')

if __name__ == '__main__':
    Timer(1, open_browser).start()
    app.run(debug=False, port=5000)